package van.planifolia.work;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * Created by Intellij IDEA<br>
 *
 * @author Planifolia.Van
 * @version 1.0
 * @date 2022/11/2 17:14
 */
public class ThreadPoolMethods {
    public static void main(String[] args) throws Exception {
        // 我们就拿定长线程池来做方法的演示吧
        ExecutorService executorService = Executors.newFixedThreadPool(6);
        // 首先就是最基础的execute方法老祖宗传下来的用来执行一个Runnable类型任务。当然在线程池中我们常常用submit方法来执行线程任务
        executorService.execute(()->{
            System.out.println("你好，我是通过execute执行的Runnable线程任务");
        });
        // 然后是submit方法，它不仅可以执行Runnable类型任务还可以执行Callable类型任务
        executorService.submit(()->{
            System.out.println("你好，我是通过submit执行的Runnable线程任务");
        });
        Future<Integer> submit = executorService.submit(() -> {
            System.out.println("我是通过submit执行的Callable任务，我可以返回数值");
            return 123;
        });
        System.out.println("我是执行的结果：" + submit.get());

        // 然后是shutdown()方法与isShutdown()，isTerminated()方法
        // 这三个方法分别是关闭线程池，判断线程池是否关闭，判断线程池任务是否执行完毕的
        // 我们创建20个任务然并且延迟执行后执行上面三个方法看看效果
        for (int i = 0; i < 20; i++) {
            int finalI = i;
            executorService.submit(()->{
                System.out.println(Thread.currentThread().getName() +":"+ finalI);
            });
        }
        // 创建一个存放callable任务的List，然后通过invokeAll来执行
        List<Callable<Object>> callables = new ArrayList<>();
        callables.add( () -> 123);
        callables.add( () -> 456);
        callables.add( () -> 789);
        callables.add( () -> 901);
        // 便利出来执行的结果
        executorService.invokeAll(callables,1,TimeUnit.MILLISECONDS).forEach(objectFuture -> {
            try {
                System.out.println("invokeAll执行结果：" + objectFuture.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });
        executorService.shutdown();
        // 那么如果我们将shouted换成shutdownNow呢？这个是立即停止线程
//        executorService.shutdownNow();
        // 显然我们可以看到线程池虽然被关闭了但是线程仍然在跑着，并且线程池中的任务也没有执行完毕，这也佐证了我们翻阅源码中所说的内容
        // 我们在使用shutdownNow方法的时候它出现了报错，sleep中断，按照我自己的理解结合shutdownNow的方法描述可以得出下面的结论
        // 当我们执行shutdownNow他会尽量将正在执行的任务终止，因为要保证安全让线程任务执行完毕自然结束是最安全的所以，他会停止那些
        /*
            还没获取到线程池资源的任务，然后会尽量终止正在执行的任务并且等待无法终止的已经获取到线程池资源的线程任务执行完毕去
         关掉线程池,对于那些还没获取到线程资源的任务则直接拒绝，然后关掉线程池。对于使用sleep阻塞的线程它自然也是不愿意等直接就给
         抛出了异常
         */
        System.out.println("线程池被关闭了吗：" + executorService.isShutdown());
        System.out.println("线程池中的任务执行完毕了吗：" + executorService.isTerminated());
    }
}
